package com.zy.chat.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zy.chat.entity.ChatGroup;
import com.zy.chat.mapper.GroupMapper;
import com.zy.chat.service.GroupService;
import com.zy.chat.session.SingleSession;
import com.zy.chat.util.ChatRedisUtils;
import com.zy.chat.vo.GroupResult;
import com.zy.chat.vo.RequestParams;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.SuggestBuilders;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class GroupServiceImpl extends ServiceImpl<GroupMapper, ChatGroup> implements GroupService {

    @Autowired
    private  GroupMapper groupMapper;

    @Autowired
    private ChatRedisUtils chatRedisUtils;

    @Autowired
            private RestHighLevelClient restHighLevelClient;

    String username;
    String content;
    String type;

    String groupname;

    @Override
    public ChatGroup selectByUserId(String username) {
        QueryWrapper<ChatGroup> chatGroupQueryWrapper = new QueryWrapper<>();
        chatGroupQueryWrapper.eq("user_name",username);
        return (groupMapper.selectOne(chatGroupQueryWrapper));
    }

    @Override
    public List<String> selectAllMembers(String groupname) {
        QueryWrapper<ChatGroup> wrapper = new QueryWrapper<>();
        wrapper.select("user_Name").eq("group_Name",groupname);
        List<ChatGroup> chatGroups = groupMapper.selectList(wrapper);
        ArrayList<String> members = new ArrayList<>();
        chatGroups.forEach(chatGroup ->members.add(chatGroup.getUserName()));
        return  members;
    }

    @Override
    public void GroupChat(ChannelHandlerContext ctx, TextWebSocketFrame msg) {
        JSONObject jsonObject = JSONObject.parseObject(msg.text());
         groupname=jsonObject.getString("groupname");
        List<String> mems= selectAllMembers(groupname);
        Set<Channel> channels=new HashSet<>();
        channels=mems.stream()
                .map(SingleSession.getUserChannelMap()::get)
                .filter(Objects::nonNull)
                .map(userChannel -> Optional.ofNullable(userChannel.channel()))
                .filter(Optional::isPresent)
                .map(Optional::get)
                .collect(Collectors.toSet());
        channels.remove(ctx.channel());
        if(!channels.equals(null)){
            for(Channel channel:channels ){
                channel.writeAndFlush(new TextWebSocketFrame(msg.text()));
            }
        }
        username=jsonObject.getString("username");
        content=jsonObject.getString("content");
        type=jsonObject.getString("type");
        Map map =chatRedisUtils.createChatNumber(groupname,username,content,type);
        chatRedisUtils.hsaveCacheChatGroupMessage(map);
    }

    @Override
    public GroupResult search(RequestParams params) {
        //准备Request
        SearchRequest request = new SearchRequest("group");
        //准备请求参数
        buildBasicQuery(params,request);
        //发送请求
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return handleResponse(response);
    }

    @Override
    public List<String> getSuggestion(String key) {
        SearchRequest request = new SearchRequest("group");//准备请求
        request.source().suggest(new SuggestBuilder().addSuggestion(
                "groupSuggest",
                SuggestBuilders.completionSuggestion("suggestion")
                        .skipDuplicates(true)
                        .prefix(key)
        ));//请求参数
        //发出请求
        SearchResponse response = null;
        try {
            response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        //解析
        Suggest suggest = response.getSuggest();
        //根据名称过去结果
        CompletionSuggestion suggestion =suggest.getSuggestion("groupSuggest");
        //获取options
        ArrayList<String> list = new ArrayList<>();
        for(CompletionSuggestion.Entry.Option option:suggestion.getOptions()){
            //获取补全的结果
            String str = option.getText().toString();
            //放入集合
            list.add(str);
        }
        return list;
    }

    private GroupResult handleResponse(SearchResponse response) {
        SearchHits searchHits = response.getHits();
        //总条数
        long total=searchHits.getTotalHits().value;
        //获取文档数组
        SearchHit[] hits = searchHits.getHits();
        //遍历
        ArrayList<ChatGroup> chatGroups = new ArrayList<>(hits.length);
        for(SearchHit hit:hits){
            //获取source
            String json=hit.getSourceAsString();
            //反序列化，非高亮的
            ChatGroup chatGroup = JSON.parseObject(json, ChatGroup.class);
            //处理高亮结果
            //获取高亮map
            Map<String, HighlightField> map = hit.getHighlightFields();
            if (map != null && !map.isEmpty()) {
                // 2）根据字段名，获取高亮结果
                HighlightField highlightField = map.get("groupname");
                if (highlightField != null) {
                    // 3）获取高亮结果字符串数组中的第1个元素
                    String hName = highlightField.getFragments()[0].toString();
                    // 4）把高亮结果放到HotelDoc中
                    chatGroup.setGroupName(hName);
                }
            }
            // 4.9.放入集合
            chatGroups.add(chatGroup);
        }
        return new GroupResult(total,chatGroups);
    }

    public void buildBasicQuery(RequestParams params,SearchRequest request){
        //准备Boolean查询
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //关键字搜索
        String key=params.getKey();
        if(StringUtils.isNotBlank(key)){
            boolQuery.must(QueryBuilders.matchQuery("groupName",key));
        }
        //设置查询条件
        request.source().query(boolQuery);
        request.source().sort("sendTime", SortOrder.DESC).size(30);
        System.out.println(request);
    }

}
